package org.net.httpclient
{
	import flash.utils.ByteArray;
	
	import org.net.data.DataPackager;

	public class HttpResponse
	{
		private var _bytes:ByteArray;
		
		private var _data:ByteArray = new ByteArray();
		
		private var _body:ByteArray = new ByteArray();
		
		private var _cursor:uint = 0; // Read position
		
		protected var _chunkLength:uint = 0; // Last chunk length
		
		
		public function HttpResponse()
		{
		}
		
		
		
		public function get bytes():ByteArray
		{
			return _bytes;
		}

		public function set bytes(value:ByteArray):void
		{
			_bytes = value;
		}
		
		
		
		/**
		 * Write bytes to the buffer.
		 *  
		 * @param bytes Data
		 */
		public function writeBytes():void {
			_data.position = _data.length;
			_data.writeBytes(bytes);      
			_data.position = _cursor;
			
			var line:String = readLine();              
			while (line != null) {
				//reach the end of header and it means the start of response body
				if (line == "\r\n" || line == "") {
					trace("===d\r\n")
					_body = new ByteArray();
					_data.readBytes(_body);
					_cursor = _data.position;
					_body.position = 0;
					trace(_body);
					readChunks();
					break;
				}
				
				line = readLine();
			}    
			
			
		}
		
		
		
		/**
		 * Read a line from the buffer.
		 * @return Next line, or null if there was no newline character found.
		 */
		public function readLine():String {    
			if (_data.bytesAvailable == 0) return null;
			
			var start:uint = _data.position;
			var bytes:ByteArray = new ByteArray();
			var foundLine:Boolean = false;
			
			while(_data.bytesAvailable > 0) {
				var char:int = _data.readByte();
				bytes.writeByte(char);
				// Char code 10 == '\n'
				if (char == 10) {
					foundLine = true;
					break; 
				}
			}
			
			var line:String = null;
			if (foundLine) {
				bytes.position = 0;
				line = bytes.readUTFBytes(bytes.length);   
				_cursor = _data.position;
				return line;        
			} else {
				// If no newline, then set the position to the original cursor position
				_data.position = _cursor;
				return null;
			}
		}
		
		
		/**
		 * Read a line from the buffer.
		 * @return Next line, or null if there was no newline character found.
		 */
		public function readLine2():String {    
			if (_body.bytesAvailable == 0) return null;
			
			var start:uint = _body.position;
			var bytes:ByteArray = new ByteArray();
			var foundLine:Boolean = false;
			
			while(_body.bytesAvailable > 0) {
				var char:int = _body.readByte();
				bytes.writeByte(char);
				// Char code 10 == '\n'
				if (char == 10) {
					foundLine = true;
					break; 
				}
			}
			
			var line:String = null;
			if (foundLine) {
				bytes.position = 0;
				line = bytes.readUTFBytes(bytes.length);   
				_cursor = _body.position;
				return line;        
			} else {
				// If no newline, then set the position to the original cursor position
				_body.position = _cursor;
				return null;
			}
		}
		
		
		public function readChunks():Boolean {
			
			while(_body.bytesAvailable > 0) {
				
				if (_chunkLength == 0) { 
					var line:String = readLine2();
					if (!line)
						throw new Error("No data available");
					
					var match:Array = line.match(/\A([0-9a-fA-F]+).*/);
					if (!match) {
						throw new Error("Invalid chunk; trying to find chunk length at line: " + line);
					}
					
					var hexlen:String = match[1];
					//Log.debug("Found hex length: " + hexlen);
					var length:Number = parseInt(hexlen, 16);
					trace("Chunk size: " + length);
					if (length <= 0) return true;
					_chunkLength = length;
				}
				
				if (_body.bytesAvailable >= (_chunkLength + 2)) {          
					var bytes:ByteArray = new ByteArray();  
					_body.readBytes(bytes, 0, _chunkLength);             
					trace("Read chunk size: " + _chunkLength);
					_body.position += 2; // Skip CRLF
					_cursor = _body.position;
					_chunkLength = 0;
					bytes.uncompress();
					var firstByte:int=bytes.readByte();
					trace(firstByte);
					
					bytes.position = 0;
					var pack:DataPackager = new DataPackager();
					pack.data = bytes;
					var results:Array=pack.readVars();
					trace(results);
				} else {
					// Back it up, copy the bytes subset into new array (to save memory) and break out
					//truncate();
					return false;
				}
			}
			
			return false;
		}

	}
}